package com.yupi.springbootinit.statemachine.processor;

import com.yupi.springbootinit.statemachine.core.StateContext;
import com.yupi.springbootinit.statemachine.core.StateProcessor;
import com.yupi.springbootinit.statemachine.enums.ProcessInstanceEventEnum;
import com.yupi.springbootinit.statemachine.enums.ProcessInstanceStateEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * 工序实例状态处理器
 * 处理工序实例状态转换的业务逻辑
 */
@Slf4j
@Component
public class ProcessInstanceStateProcessor implements StateProcessor<ProcessInstanceStateEnum, ProcessInstanceEventEnum> {
    
    @Override
    public boolean beforeTransition(StateContext context) {
        log.info("工序实例状态转换前置处理: 实体[{}] {} -> {}", 
            context.getEntityId(),
            context.getCurrentState().getCode(),
            context.getTargetState().getCode());
        
        ProcessInstanceStateEnum currentState = (ProcessInstanceStateEnum) context.getCurrentState();
        ProcessInstanceStateEnum targetState = (ProcessInstanceStateEnum) context.getTargetState();
        
        switch (currentState) {
            case PENDING:
                return handlePendingToInProgress(context);
            case IN_PROGRESS:
                return handleInProgressTransition(context, targetState);
            case PENDING_INSPECTION:
                return handlePendingInspectionToInspecting(context);
            case INSPECTING:
                return handleInspectingTransition(context, targetState);
            case REJECTED:
                return handleRejectedToInProgress(context);
            default:
                return true;
        }
    }
    
    @Override
    public void afterTransition(StateContext context) {
        log.info("工序实例状态转换后置处理: 实体[{}] 转换完成", context.getEntityId());
        
        ProcessInstanceStateEnum targetState = (ProcessInstanceStateEnum) context.getTargetState();
        
        // 根据目标状态执行相应的后置处理
        switch (targetState) {
            case IN_PROGRESS:
                handleAfterStartProcess(context);
                break;
            case PENDING_INSPECTION:
                handleAfterRequestInspection(context);
                break;
            case COMPLETED:
                handleAfterCompleteProcess(context);
                break;
            case REJECTED:
                handleAfterRejectProcess(context);
                break;
        }
        
        // 发送通知
        sendNotification(context);
        
        // 检查是否需要自动推进下一工序
        checkAndReleaseNextProcess(context);
    }
    
    @Override
    public void onTransitionError(StateContext context, Exception exception) {
        log.error("工序实例状态转换失败: 实体[{}] {} -> {}, 错误: {}", 
            context.getEntityId(),
            context.getCurrentState().getCode(),
            context.getTargetState().getCode(),
            exception.getMessage());
        
        // 记录错误并发送告警
        recordError(context, exception);
    }
    
    @Override
    public String getSupportedStateType() {
        return "PROCESS_INSTANCE";
    }
    
    /**
     * 处理待开始到进行中的转换
     */
    private boolean handlePendingToInProgress(StateContext context) {
        Long processInstanceId = context.getEntityId();
        log.debug("检查工序实例[{}]开始条件", processInstanceId);
        
        // 检查前序工序是否已完成
        if (!checkPreviousProcessCompleted(processInstanceId)) {
            log.warn("工序实例[{}]前序工序未完成，不能开始", processInstanceId);
            return false;
        }
        
        // 检查资源是否可用
        if (!checkResourceAvailable(processInstanceId)) {
            log.warn("工序实例[{}]所需资源不可用", processInstanceId);
            return false;
        }
        
        return true;
    }
    
    /**
     * 处理进行中状态的转换
     */
    private boolean handleInProgressTransition(StateContext context, ProcessInstanceStateEnum targetState) {
        Long processInstanceId = context.getEntityId();
        
        if (targetState == ProcessInstanceStateEnum.PENDING_INSPECTION) {
            // 转换到待检验，检查工序是否需要检验
            return checkInspectionRequired(processInstanceId);
        } else if (targetState == ProcessInstanceStateEnum.COMPLETED) {
            // 直接完成，检查工序是否可以跳过检验
            return !checkInspectionRequired(processInstanceId);
        }
        
        return true;
    }
    
    /**
     * 处理待检验到检验中的转换
     */
    private boolean handlePendingInspectionToInspecting(StateContext context) {
        Long processInstanceId = context.getEntityId();
        log.debug("检查工序实例[{}]检验条件", processInstanceId);
        
        // 检查品质部是否有可用检验员
        return checkInspectorAvailable(processInstanceId);
    }
    
    /**
     * 处理检验中状态的转换
     */
    private boolean handleInspectingTransition(StateContext context, ProcessInstanceStateEnum targetState) {
        Long processInstanceId = context.getEntityId();
        
        if (targetState == ProcessInstanceStateEnum.COMPLETED) {
            // 检验合格
            log.info("工序实例[{}]检验合格", processInstanceId);
            return true;
        } else if (targetState == ProcessInstanceStateEnum.REJECTED) {
            // 检验不合格
            log.info("工序实例[{}]检验不合格，需要返工", processInstanceId);
            return true;
        }
        
        return false;
    }
    
    /**
     * 处理不合格返工到进行中的转换
     */
    private boolean handleRejectedToInProgress(StateContext context) {
        Long processInstanceId = context.getEntityId();
        log.info("工序实例[{}]开始返工", processInstanceId);
        
        // 记录返工次数
        recordReworkCount(processInstanceId);
        
        return true;
    }
    
    /**
     * 工序开始后的处理
     */
    private void handleAfterStartProcess(StateContext context) {
        Long processInstanceId = context.getEntityId();
        
        // 更新工序开始时间
        updateProcessStartTime(processInstanceId);
        
        // 分配执行人员
        assignOperator(processInstanceId, context.getOperatorId());
        
        log.info("工序实例[{}]已开始，执行人: {}", processInstanceId, context.getOperatorName());
    }
    
    /**
     * 申请检验后的处理
     */
    private void handleAfterRequestInspection(StateContext context) {
        Long processInstanceId = context.getEntityId();
        
        // 创建检验任务
        createInspectionTask(processInstanceId);
        
        // 通知品质部
        notifyQualityDepartment(processInstanceId);
        
        log.info("工序实例[{}]已申请检验", processInstanceId);
    }
    
    /**
     * 工序完成后的处理
     */
    private void handleAfterCompleteProcess(StateContext context) {
        Long processInstanceId = context.getEntityId();
        
        // 更新工序完成时间
        updateProcessCompleteTime(processInstanceId);
        
        // 记录实际参数
        recordActualParameters(processInstanceId, context);
        
        log.info("工序实例[{}]已完成", processInstanceId);
    }
    
    /**
     * 工序不合格后的处理
     */
    private void handleAfterRejectProcess(StateContext context) {
        Long processInstanceId = context.getEntityId();
        
        // 生成返工任务
        createReworkTask(processInstanceId);
        
        // 通知生产部
        notifyProductionDepartment(processInstanceId);
        
        log.info("工序实例[{}]检验不合格，已生成返工任务", processInstanceId);
    }
    
    /**
     * 发送通知
     */
    private void sendNotification(StateContext context) {
        ProcessInstanceStateEnum targetState = (ProcessInstanceStateEnum) context.getTargetState();
        Long processInstanceId = context.getEntityId();
        
        switch (targetState) {
            case IN_PROGRESS:
                log.info("通知相关人员: 工序实例[{}]已开始", processInstanceId);
                break;
            case PENDING_INSPECTION:
                log.info("通知品质部: 工序实例[{}]待检验", processInstanceId);
                break;
            case COMPLETED:
                log.info("通知相关人员: 工序实例[{}]已完成", processInstanceId);
                break;
            case REJECTED:
                log.info("通知生产部: 工序实例[{}]需要返工", processInstanceId);
                break;
        }
    }
    
    /**
     * 检查并释放下一工序
     */
    private void checkAndReleaseNextProcess(StateContext context) {
        if (context.getTargetState() == ProcessInstanceStateEnum.COMPLETED) {
            Long processInstanceId = context.getEntityId();
            
            // 查找下一工序并设置为可开始状态
            releaseNextProcess(processInstanceId);
            
            log.info("工序实例[{}]完成，已释放下一工序", processInstanceId);
        }
    }
    
    // 以下为业务逻辑方法的简化实现，实际项目中需要调用相应的服务
    
    private boolean checkPreviousProcessCompleted(Long processInstanceId) {
        // 检查前序工序是否完成
        return true; // 简化实现
    }
    
    private boolean checkResourceAvailable(Long processInstanceId) {
        // 检查设备、人员等资源是否可用
        return true; // 简化实现
    }
    
    private boolean checkInspectionRequired(Long processInstanceId) {
        // 检查工序是否需要检验
        return true; // 简化实现，实际需要查询工艺单配置
    }
    
    private boolean checkInspectorAvailable(Long processInstanceId) {
        // 检查是否有可用的检验员
        return true; // 简化实现
    }
    
    private void recordReworkCount(Long processInstanceId) {
        // 记录返工次数
        log.debug("记录工序实例[{}]返工次数", processInstanceId);
    }
    
    private void updateProcessStartTime(Long processInstanceId) {
        // 更新工序开始时间
        log.debug("更新工序实例[{}]开始时间", processInstanceId);
    }
    
    private void assignOperator(Long processInstanceId, Long operatorId) {
        // 分配执行人员
        log.debug("为工序实例[{}]分配执行人员[{}]", processInstanceId, operatorId);
    }
    
    private void createInspectionTask(Long processInstanceId) {
        // 创建检验任务
        log.debug("为工序实例[{}]创建检验任务", processInstanceId);
    }
    
    private void notifyQualityDepartment(Long processInstanceId) {
        // 通知品质部
        log.debug("通知品质部检验工序实例[{}]", processInstanceId);
    }
    
    private void updateProcessCompleteTime(Long processInstanceId) {
        // 更新工序完成时间
        log.debug("更新工序实例[{}]完成时间", processInstanceId);
    }
    
    private void recordActualParameters(Long processInstanceId, StateContext context) {
        // 记录实际参数
        log.debug("记录工序实例[{}]实际参数", processInstanceId);
    }
    
    private void createReworkTask(Long processInstanceId) {
        // 生成返工任务
        log.debug("为工序实例[{}]生成返工任务", processInstanceId);
    }
    
    private void notifyProductionDepartment(Long processInstanceId) {
        // 通知生产部
        log.debug("通知生产部工序实例[{}]需要返工", processInstanceId);
    }
    
    private void releaseNextProcess(Long processInstanceId) {
        // 释放下一工序
        log.debug("释放工序实例[{}]的下一工序", processInstanceId);
    }
    
    private void recordError(StateContext context, Exception exception) {
        // 记录错误信息
        log.error("工序实例[{}]状态转换错误: {}", context.getEntityId(), exception.getMessage());
    }
}